package org.polyforms.repository.spring;

import java.lang.reflect.Method;

import org.polyforms.repository.intercept.AutoAttachableInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionAttributeSource;

/**
 * {@link org.springframework.aop.Advisor} for methods which parameters might be attached automatically.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
@Component
public final class AutoAttachableAdvisor extends DefaultPointcutAdvisor {
    private static final long serialVersionUID = 1L;
    private static final int ORDER = 200;

    private TransactionAttributeSource transactionAttributeSource;

    /**
     * Create an instance with {@link AutoAttachableInterceptor}.
     */
    @Autowired
    public AutoAttachableAdvisor(final AutoAttachableInterceptor autoAttachableInterceptor) {
        super(autoAttachableInterceptor);
        setPointcut(new TransactionAttributePointcut());
        setOrder(ORDER);
    }

    /**
     * Set {@link TransactionAttributeSource}.
     */
    @Autowired(required = false)
    public void setTransactionAttributeSource(final TransactionAttributeSource transactionAttributeSource) {
        this.transactionAttributeSource = transactionAttributeSource;
    }

    private class TransactionAttributePointcut extends StaticMethodMatcherPointcut {
        /**
         * {@inheritDoc}
         */
        public boolean matches(final Method method, final Class<?> targetClass) {
            return transactionAttributeSource != null
                    && transactionAttributeSource.getTransactionAttribute(method, targetClass) != null;
        }
    }
}
